<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .map{
            width:800px;
            height:600px;
            background-color:#222;
            position:relative;
            margin: 50px auto 0;
        }
      </style>
    </head>
    <body>
    <div class="map"></div>
    <script>
        //食物就是一个对象，有宽，高，颜色，位置坐标（横纵坐标），先定义构造函数，在创建对象
        (function(){
            var elements=[];//用来保存每个小方块食物的
            //要创建食物的对象，就需要定义一个构造函数
            function Food(x,y,width,height,color){
                //食物的横纵坐标,并设置初始值
                this.x=x||0;
                this.y=y||0;
                //食物的宽高，并设置初始值
                this.width=width||20;
                this.height=height||20;
                //背景颜色
                this.color=color||"#6ff";	
            }
            //为原型添加初始化方法，使得食物显示在地图上
            //因为食物需要在地图上显示，因此需要map参数
            Food.prototype.init=function(map){
                //先删除一次食物
                remove();
                //创建div
                var div=document.createElement("div");
                //将div添加到map中
                map.appendChild(div);
                //设置div的样式
                div.style.width=this.width+"px";
                div.style.height=this.height+"px";
                div.style.backgroundColor=this.color;
                //先脱离文档流
                div.style.position="absolute";
                //随机坐标的产生
                this.x=parseInt(Math.random()*(map.offsetWidth/this.width))*this.width;
                this.y=parseInt(Math.random()*(map.offsetHeight/this.height))*this.height;
                div.style.left=this.x+"px";
                div.style.top=this.y+"px";
                
                //把div加入到数组elements中
                elements.push(div);
            }
            //删除食物
            function remove(){
                //elements数组中有这个食物
                for(var i=0;i<elements.length;i++){
                    var ele = elements[i];
                    //找到这个子元素的父级元素，然后删除这个子元素
                    ele.parentNode.removeChild(ele);
                    //再次把elements数组清空
                    elements.splice(i, 1);
                }
                
            }
            //把Food暴露给Window,外部可以使用
            window.Food=Food;
        }());
        
        
        
        
        
        //小蛇
        (function(){
            var elements=[];//存放小蛇的每个身体部分
            //小蛇的构造函数
            function Snake(width,height,direction){
                //小蛇的每个部分的宽
                this.width=width||20;
                this.height=height||20;
                //小蛇的身体
                this.body=[
                    {x:3,y:2,color:"red"},
                    {x:2,y:2,color:"orange"},
                    {x:1,y:2,color:"orange"}
                ];
                
                //方向
                this.direction=direction||"right";
                
            }
            //小蛇初始化的方法
            Snake.prototype.init=function(map){
                //删除小蛇
                remove();
                //循环创建div
                for(var i=0;i<this.body.length;i++){
                    //数组中的每个数组元素都是一个对象
                    var obj=this.body[i];
                    //创建div
                    var div=document.createElement("div"); 
                    //将div添加到map中
                    map.appendChild(div);
                    //设置div的样式
                    div.style.position="absolute";
                    div.style.width=this.width+"px";
                    div.style.height=this.height+"px";
                    //横纵坐标
                    div.style.left=obj.x*this.width+"px";
                    div.style.top=obj.y*this.height+"px";
                    //设置背景颜色
                    div.style.backgroundColor=obj.color;
                    
                    //方向暂时不定
                    //把div加入到elements数组中----目的是为了删除
                    elements.push(div);
                }
            };
            //小蛇的移动
            Snake.prototype.move=function(food,map){
                //改变小蛇身体的坐标
                var i=this.body.length-1;
                for(;i>0;i--){
                    this.body[i].x=this.body[i-1].x;
                    this.body[i].y=this.body[i-1].y;
                }
                //改变蛇头的方向
                
                switch(this.direction){
                    case "right":
                        this.body[0].x+=1;
                        break;
                    case "left":
                        this.body[0].x-=1;
                        break;
                    case "top":
                        this.body[0].y-=1;
                        break;
                    case "bottom":
                        this.body[0].y+=1;
                        break;
                    
                }
                //判断小蛇是否吃到食物
                var headX=this.body[0].x*this.width;
                var headY=this.body[0].y*this.height;
                var foodX=food.x;
                var foodY=food.y;
                //小蛇吃到食物
                if(headX==foodX && headY==foodY){
                    //身体变长
                    var last=this.body[this.body.length-1];
                    this.body.push({
                        x:last.x,
                        y:last.y,
                        color:last.color
                    });
                    //把食物删除,重新初始化食物
                    food.init(map);
                }
            };
            //删除小蛇的私有函数
            function remove(){
                //获取数组
                var i=elements.length-1;
                for(;i>=0;i--){
                    //先找到当前子元素的父级元素，然后删除该元素
                    var ele=elements[i];
                    ele.parentNode.removeChild(ele);
                    //清空数组
                    elements.splice(i,1);
                }
                
            }
            
            //把Snake暴露给window,外部可以访问
            window.Snake=Snake;
        }());
        
        
        
        
        
        
        //游戏对象
        (function(){
            var that=null;
            //游戏的构造函数
            function Game(map){
                this.food=new Food;//食物对象
                this.snake=new Snake;//小蛇对象
                this.map=map;//地图
                that=this;//将实例对象赋值给that
            }
            //初始化游戏
            Game.prototype.init=function(){
                that.food.init(this.map);
                that.snake.init(this.map);
                //调用小蛇自动移动函数
                this.runSnake(this.food,this.map);
                //调用按键的方法，从而改变蛇头方向
                this.bindKey();
            };
            
            //设置小蛇可以自动的移动
            Game.prototype.runSnake=function(food,map){
                //小蛇自行移动
                var timeId=setInterval(function(){
                    
                    //这里的this是window
                    //移动小蛇
                    this.snake.move(food,map);
                    //初始化小蛇
                    this.snake.init(map);
                    //横坐标的最大值
                    var maxX=map.offsetWidth/this.snake.width;
                    //纵坐标的最大值
                    var maxY=map.offsetHeight/this.snake.height;
                    //获取小蛇蛇头的实时坐标
                    var headX=this.snake.body[0].x;
                    var headY=this.snake.body[0].y;
                    if(headX<0||headX>=maxX){
                        //撞墙了，停止定时器
                        clearInterval(timeId);
                        alert("游戏结束");
                    }
                    if(headY<0||headY>=maxY){
                        //撞墙了，停止定时器
                        clearInterval(timeId);
                        alert("游戏结束");
                    }
                }.bind(that),150);//改变this的指向
                
            };
            
            //用户按键改变小蛇的方向
            Game.prototype.bindKey=function(){
                //这里的this应该是触发keydown的事件的对象---document,
                //所以,这里的this就是document
                //获取按键的值
                document.addEventListener("keydown",function(e){
                    switch(e.keyCode){
                        case 37:this.snake.direction="left";break;
                        case 38:this.snake.direction="top";break;
                        case 39:this.snake.direction="right";break;
                        case 40:this.snake.direction="bottom";break;
                    }
                
                }.bind(that),false);
            };
            //把Game暴露给window,外部就可以访问Game对象了
            window.Game=Game;
        }());
        
        
        
        
        
         //初始化游戏对象
        var gm = new Game(document.querySelector(".map"));
     
        //初始化游戏---开始游戏
        gm.init();
        
        
    </script>

</html>